﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SymbolIntegration.core;
using SymbolIntegration.core.Expressions;
using SymbolIntegration.core.Expressions.Functions;
using SymbolIntegration.core.Helpers;

namespace AnalyticIntegration.DefaultIntergators
{
    public class LnIntegrator : IIntegrator
    {
        public bool CanIntegrate(List<Expression> multipliers, ExpressionStatistic statistic, string variable)
        {
            bool isCan = false;
            do
            {
                if (statistic.Functions.Count != 1 || statistic.HasUnpolinomicPowers ||
                    statistic.HasUnintegratedExpression)
                {
                    break;
                }

                var functionStatistic = statistic.Functions.First();
                if (functionStatistic.Type != FunctionType.Ln)
                {
                    break;
                }

                if (functionStatistic.ArgumentPolinomMaxPower == null || functionStatistic.ArgumentPolinomMaxPower.Value > 1)
                {
                    break;
                }

                if (multipliers.Count != 2)
                {
                    break;
                }

                isCan = true;
            } 
            while (false);

            return isCan;

        }

        public Expression TryIntegrateMultipliers(List<Expression> multipliers, string variable)
        {
            var lnFunction = multipliers[0] as LnFunction;
            Expression otherExpression = null;
            if (lnFunction == null)
            {
                lnFunction = multipliers[1] as LnFunction;
                otherExpression = multipliers[0];
            }
            else
            {
                otherExpression = multipliers[1];
            }

            var polinom = lnFunction.Argument.FormatToPolinom(variable);
            var a = polinom.GetConstantAt(1);
            var b = polinom.GetConstantAt(0);

            var substituted = (new VariableExpression(variable) - b)/a;
            substituted = substituted.Normalize();
            var toIntegrate = ExpressionFacade.Substitude(otherExpression, substituted, variable);
            var lnToUntegrate = new LnFunction(new VariableExpression(variable));
            Expression result;
            if (toIntegrate.Type == ExpressionType.Addends)
            {
                result = IntegrationHelper.Integrate(lnToUntegrate * toIntegrate, variable);
            }
            else
            {
                var integratedExp = Expression.Integrate(toIntegrate, variable, this);
                var firstPartOfResult = lnToUntegrate * integratedExp;
                var secondPartOfResult = integratedExp / new VariableExpression(variable);
                secondPartOfResult = Expression.Integrate(secondPartOfResult, variable, this);
                result = firstPartOfResult - secondPartOfResult;
            }

            result = ExpressionFacade.Substitude(result / a, lnFunction.Argument, variable);
            return result;
        }
    }
}
